home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / alpha.arc / ICMP.C < prev    next >
C/C++ Source or Header  |  1988-07-02  |  5KB  |  200 lines

  1. /* Internet Control Message Protocol */
  2. #include "global.h"
  3. #include "mbuf.h"
  4. #include "internet.h"
  5. #include "timer.h"
  6. #include "iface.h"
  7. #include "ip.h"
  8. #include "icmp.h"
  9.  
  10. struct icmp_errors icmp_errors;
  11. struct icmp_stats icmp_stats;
  12.  
  13. /* Process an incoming ICMP packet */
  14. void
  15. icmp_input(bp,protocol,source,dest,tos,length,rxbroadcast)
  16. struct mbuf *bp;    /* Pointer to ICMP message */
  17. char protocol;        /* Should always be ICMP_PTCL */
  18. int32 source;        /* Sender of ICMP message */
  19. int32 dest;        /* Us */
  20. char tos;        /* Type of Service */
  21. int16 length;        /* Length of ICMP message */
  22. char rxbroadcast;
  23. {
  24.     struct mbuf *htonicmp(),*tbp;
  25.     struct icmp icmp;    /* ICMP header */
  26.     struct ip ip;        /* Offending datagram header */
  27.     int16 type;        /* Type of ICMP message */
  28.  
  29.     if(rxbroadcast){
  30.         /* Broadcast ICMP packets are to be IGNORED !! */
  31.         icmp_errors.bdcsts++;
  32.         free_p(bp);
  33.         return;
  34.     }
  35.     if(cksum(NULLHEADER,bp,length) != 0){
  36.         /* Bad ICMP checksum; discard */
  37.         icmp_errors.checksum++;
  38.         free_p(bp);
  39.         return;
  40.     }
  41.     ntohicmp(&icmp,&bp);
  42.  
  43.     /* Process the message. Some messages are passed up to the protocol
  44.      * module for handling, others are handled here.
  45.      */
  46.     type = icmp.type;
  47.     if(type < ICMP_TYPES)
  48.         icmp_stats.input[type]++;
  49.  
  50.     switch(uchar(type)){
  51.     case TIME_EXCEED:    /* Time-to-live Exceeded */
  52.     case DEST_UNREACH:    /* Destination Unreachable */
  53.     case QUENCH:        /* Source Quench */
  54.         ntohip(&ip,&bp);    /* Extract offending IP header */
  55.         switch(uchar(ip.protocol)){
  56.         case TCP_PTCL:
  57.             tcp_icmp(ip.source,ip.dest,icmp.type,icmp.code,&bp);
  58.             break;
  59.         }
  60.         break;
  61.     case ECHO:        /* Echo Request */
  62.         /* Change type to ECHO_REPLY, recompute checksum,
  63.          * and return datagram.
  64.          */
  65.         icmp.type = ECHO_REPLY;
  66.         if((tbp = htonicmp(&icmp,bp)) == NULLBUF){
  67.             free_p(bp);
  68.             return;
  69.         }
  70.         icmp_stats.output[ECHO_REPLY]++;
  71.         ip_send(dest,source,ICMP_PTCL,tos,0,tbp,length,0,0);
  72.         return;
  73.     case REDIRECT:        /* Redirect */
  74.     case PARAM_PROB:    /* Parameter Problem */
  75.         break;
  76.        case ECHO_REPLY:        /* Echo Reply */
  77.         echo_proc(source,dest,&icmp);
  78.         break;
  79.     case TIMESTAMP:        /* Timestamp */
  80.     case TIME_REPLY:    /* Timestamp Reply */
  81.     case INFO_RQST:        /* Information Request */
  82.     case INFO_REPLY:    /* Information Reply */
  83.         break;
  84.     }
  85.     free_p(bp);
  86. }
  87. /* Return an ICMP response to the sender of a datagram.
  88.  * Unlike most routines, the callER frees the mbuf.
  89.  */
  90. int
  91. icmp_output(ip,data,type,code,args)
  92. struct ip *ip;        /* Header of offending datagram */
  93. struct mbuf *data;    /* Data portion of datagram */
  94. char type,code;        /* Codes to send */
  95. union icmp_args *args;
  96. {
  97.     struct mbuf *htonicmp();
  98.     struct mbuf *htonip();
  99.     struct mbuf *bp;
  100.     struct icmp icmp;    /* ICMP protocol header */
  101.     int16 dlen;        /* Length of data portion of offending pkt */
  102.     int16 length;        /* Total length of reply */
  103.     extern int32 ip_addr;    /* Our IP address */
  104.  
  105.     if(ip == NULLIP)
  106.         return -1;
  107.     if(type < ICMP_TYPES)
  108.         icmp_stats.output[type]++;
  109.  
  110.     if(uchar(ip->protocol) == ICMP_PTCL){
  111.         /* Never send an ICMP message about another ICMP message */
  112.         icmp_errors.noloop++;
  113.         return -1;
  114.     }
  115.     /* Compute amount of original datagram to return.
  116.      * We return the original IP header, and up to 8 bytes past that.
  117.      */
  118.     dlen = min(8,len_mbuf(data));
  119.     length = dlen + ICMPLEN + IPLEN + ip->optlen;
  120.     /* Take excerpt from data portion */
  121.     if(data != NULLBUF && (bp = copy_p(data,dlen)) == NULLBUF)
  122.         return -1;    /* The caller will free data */
  123.  
  124.     /* Recreate and tack on offending IP header */
  125.     if((data = htonip(ip,bp)) == NULLBUF){
  126.         free_p(bp);
  127.         return -1;
  128.     }
  129.     icmp.type = type;
  130.     icmp.code = code;
  131.     switch(uchar(icmp.type)){
  132.     case PARAM_PROB:
  133.         icmp.args.pointer = args->pointer;
  134.         break;
  135.     case REDIRECT:
  136.         icmp.args.address = args->address;
  137.         break;
  138.     case ECHO:
  139.     case ECHO_REPLY:
  140.     case INFO_RQST:
  141.     case INFO_REPLY:
  142.     case TIMESTAMP:
  143.     case TIME_REPLY:
  144.         icmp.args.echo.id = args->echo.id;
  145.         icmp.args.echo.seq = args->echo.seq;
  146.         break;
  147.     default:
  148.         icmp.args.unused = 0;
  149.         break;
  150.     }
  151.     /* Now stick on the ICMP header */
  152.     if((bp = htonicmp(&icmp,data)) == NULLBUF){
  153.         free_p(data);
  154.         return -1;
  155.     }
  156.     return ip_send(ip_addr,ip->source,ICMP_PTCL,ip->tos,0,bp,length,0,0);
  157. }
  158. /* Generate ICMP header in network byte order, link data, compute checksum */
  159. struct mbuf *
  160. htonicmp(icmp,data)
  161. struct icmp *icmp;
  162. struct mbuf *data;
  163. {
  164.     struct mbuf *bp;
  165.     register char *cp;
  166.     int16 checksum;
  167.  
  168.     if((bp = pushdown(data,ICMPLEN)) == NULLBUF)
  169.         return NULLBUF;
  170.     cp = bp->data;
  171.  
  172.     *cp++ = icmp->type;
  173.     *cp++ = icmp->code;
  174.     cp = put16(cp,0);        /* Clear checksum */
  175.     cp = put16(cp,icmp->args.echo.id);
  176.     cp = put16(cp,icmp->args.echo.seq);
  177.  
  178.     /* Compute checksum, and stash result */
  179.     checksum = cksum(NULLHEADER,bp,len_mbuf(bp));
  180.     cp = &bp->data[2];
  181.     cp = put16(cp,checksum);
  182.  
  183.     return bp;
  184. }
  185. /* Pull off ICMP header */
  186. int
  187. ntohicmp(icmp,bpp)
  188. struct icmp *icmp;
  189. struct mbuf **bpp;
  190. {
  191.     if(icmp == (struct icmp *)NULL)
  192.         return -1;
  193.     icmp->type = pullchar(bpp);
  194.     icmp->code = pullchar(bpp);
  195.     (void) pull16(bpp);        /* Toss checksum */
  196.     icmp->args.echo.id = pull16(bpp);
  197.     icmp->args.echo.seq = pull16(bpp);
  198.     return 0;
  199. }
  200.